Skip to content

fix: Android で全 wss:// 接続が失敗する問題を webpki-roots で修正#28

Merged
hitalin merged 1 commit into
mainfrom
fix/android-ws-webpki-roots
Jul 2, 2026
Merged

fix: Android で全 wss:// 接続が失敗する問題を webpki-roots で修正#28
hitalin merged 1 commit into
mainfrom
fix/android-ws-webpki-roots

Conversation

@hitalin

@hitalin hitalin commented Jul 2, 2026

Copy link
Copy Markdown
Owner

真因 (hitalin/notedeck#506)

Android 実機で「REST は正常なのにストリームイベントが一切届かない」問題のコード精査で特定。

  • tokio-tungstenite を rustls-tls-native-roots のみで使用していた
  • Android では rustls-native-certs 0.8 → openssl-probe 0.2 が Termux 専用パスしか探索せず証明書 0 件 → tokio-tungstenite (tls.rs) が no native root CA certificates found全 wss:// 接続を即 Err
  • notecli の再接続ループは初回接続成功後にしか spawn されないため、初回失敗は無音で恒久化
  • REST (reqwest rustls-tls = webpki-roots 同梱) は正常、デスクトップ (OS cert store が読める) も正常 — 実機の全観測と整合

修正

rustls-tls-webpki-roots feature を併用。tokio-tungstenite 0.26.2 の tls.rs:108-123 は両 feature 有効時「native certs 0 件は非致命」となり Mozilla 同梱ルートへフォールバックする (vendored source で確認済み)。デスクトップは native 優先のまま変化なし。REST 側と同じ信頼モデルに揃う。

検証

  • cargo check / cargo test 169 件通過
  • tokio-tungstenite の該当フォールバックコードを直接確認

関連する構造的課題 (別対応)

初回接続失敗時に再接続ループが始まらない構造は残る (今回のトリガーは消える)。connect() を「失敗しても connection_task を spawn して loop に任せる」形に直すのは semantics 変更を伴うため別 PR で検討。

🤖 Generated with Claude Code

tokio-tungstenite を rustls-tls-native-roots のみで使っていたため、
Android では root 証明書の探索 (rustls-native-certs → openssl-probe)
が Termux 専用パスしか見ず 0 件になり、全 WebSocket 接続が TLS 段階で
必ず失敗していた。さらに notecli の再接続ループは初回接続成功後にしか
起動しないため、失敗は無音で恒久化していた (notedeck#506 の真因)。

rustls-tls-webpki-roots を併用すると tokio-tungstenite (tls.rs) は
native certs 0 件を非致命として Mozilla 同梱ルートにフォールバック
する。REST 側 (reqwest rustls-tls = webpki-roots) と同じ信頼モデルに
揃い、デスクトップは従来どおり native 優先のまま。
@hitalin hitalin merged commit f510fb8 into main Jul 2, 2026
1 check passed
hitalin added a commit to hitalin/notedeck that referenced this pull request Jul 2, 2026
コード精査で確定した 2 つの構造欠陥への対処:

- StreamingManager の manage が emit_accounts_early の後にあり、
  アカウント一覧を受けた JS が即 query_subscribe_* を invoke すると
  "state not managed" で即死する race があった。manage を前に移動
- query 購読の open() は一度失敗すると再試行経路がなく、WS が後で
  復活しても Rust 側に購読が存在せず replay 対象にならないため
  「WS connected 表示なのにイベント永久ゼロ」に固定されていた。
  notecli の再接続ループと同じ Equal Jitter バックオフ (cap 30s、
  dispose で中断) で成功するまで再試行する自己回復ループに変更

Android で全 wss:// が失敗する主因 (TLS ルート証明書) は notecli 側
hitalin/notecli#28 で修正。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant